package com.functest.orm

import com.functest.util.OrmUtil
import groovy.sql.Sql

/**
 * @author DavydovMD
 * Date: 05.04.13
 * Time: 13:06
 */
class SingleDbTableMapper<T> extends AbstractTableMapper {
    Closure<Sql> dbGetter
    Class<T> beanClass
    @Lazy
    String dbUrl = { (SqlMappingUtil.getDbUrl(dbGetter())) }()

    SingleDbTableMapper(Mapper mapper, Closure<Sql> dbGetter, String tableName, String keyField = null, Class beanClass = HashMap.class) {
        super(mapper, tableName, keyField)
        this.dbGetter = dbGetter
        this.beanClass = beanClass
    }

    SingleDbTableMapper(MapperFields builder, Closure<Sql> dbGetter, String tableName, String keyField = null, Class beanClass = HashMap.class) {
        super(builder, tableName, keyField)
        this.dbGetter = dbGetter
        this.beanClass = beanClass
    }

    /**
     * Current design of whole fully qualified field name is nonsence and must be reviewed
     * @return
     */
    String getPrefix() {
        "${OrmUtil.lastToken(beanClass.name)}.$tableName."
    }

    /**
     * Deprecated. Use Provider or, at least, QueryBuilder instead
     * @param value
     * @param fieldName
     * @return
     */
    @Deprecated
    Map fromDbFirstRowAsMap(def value, String fieldName = keyField) {
        Map ret = SqlMappingUtil.simpleSelectFirstRowAsMap(dbGetter(), tableName, this, fieldName, value)
        if (!ret) throw new NoSuchFieldError("No data found for query [${fieldName} = ${value}]")
        this.transformMap(ret)
    }

    /**
     * Returns fully qualified table name (for use in SQL queries)
     * MSSQL-specific implementation
     * @return table name in quotes for use in SQL queries
     */
    //TODO: Make it RDBMS agnostic - move all SQL engine-related stuff to separate classes
    String getFqTableName() {
        tableName.contains('[') ? tableName : "\"${tableName}\""
    }

    /**
     * MSSQL-specific implementation
     * @return last part of table name: WITHOUT database and/or server qualifiers
     */
    String getShortTableName() {
        if (tableName.contains('['))
            "\"${OrmUtil.lastToken(tableName)}\""
        else
            "\"$tableName\""
    }

    /**
     * Works ONLY for single-column-sourced fields. For multicolumn fields returns null
     * MSSQL-specific implementation!
     * @param field
     * @return fully qualified name of a column, field is sourced from. If field is multi-column, null
     */
    @Override
    String getFqSourceName(String field) {
        List from = getField(field).from
        if (from.size() != 1) return null
        "${shortTableName}.\"${from.last()}\""
    }

    /**
     * Get fully qualified name(s) of source column(s), which includes table name.
     * Important: currently, implementation is MSSQL-specific, and might not work with other databases
     * @param field
     * @return
     */
    @Override
    Map<String, String> getFqSourceNames(String field) {
        Map ret = [:]
        builder.getField(field).from.each { String s ->
            ret.put(s, "${shortTableName}.\"${s}\"" as String)
        }
        ret
    }

    /**
     * Deprecated. Mappers are not used directly to produce SQL queries anymore.
     * @return
     */
    @Deprecated
    String getAllFieldsListClause() {
        this.builder.mappedFields().join(',')
    }

    /**
     * Returns QueryBuilder() for the mapper, which is the object that can be actually used to query database for objects of our class
     * @return
     */
    QueryBuilder queryBuilder() {
        new SingleDbQueryBuilder(this, beanClass)
    }
}





